package dataProcess;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import ds.WordSet;
import ds.Constants;
import util.StringUtils;


public class StringSpliter {
	private WordSet stopWords;
	
	public static StringSpliter instance = null;
	
	public StringSpliter(){
		this. stopWords = new WordSet();
	}
	
	public StringSpliter(WordSet stopWords){
		this. stopWords = stopWords;
	}
	
	public static StringSpliter getDefaultSpliter(){
		if(instance == null){
			WordSet stopWords = new WordSet(Constants.stopwords);
			instance = new StringSpliter(stopWords);
		} 
		return instance;
	}
	
	/**
	 * pure method to split sentence into words, don't split Words, don't use WordNet, don't split wordMap (CVSUIPlugin)
	 * @param sentence
	 * @return
	 */
	public String simpleSplitSentenceIntoWords(String sentence) {
		
		String result = replaceSymbolByRegex(sentence, Constants.regexNonSingleQuotDelimiters);
		//result = removeStopWord(result);
		
		result = replaceSymbolByRegex(result, Constants.regexNonAlphDelimiters);
		//result = removeStopWord(result);
		
		result = replaceSymbolByRegex(result, Constants.regexEnterSpaceDelimiters);
		
		StringBuilder builder = new StringBuilder();
		
		String[] words = result.split(" ");
		for(String word : words){		
			if(word.trim().equals("")) continue;
			
			List<String> subWords = splitWordIntoWords(word);
			for(String keyWord : subWords){
				if(keyWord.length() < Constants.minWordLength)  continue;
				builder.append(StringUtils.firstUpperCase(keyWord.toLowerCase())).append(" ");			
			}
		}
		return builder.toString().trim();
	}
	
	private String removeStopWord(String sentence) {
		String[] words = sentence.split(" ");
		StringBuilder builder = new StringBuilder();
		for(String word : words){
			word = word.trim();			
			if(word.equals("")) continue;
			
			if(!stopWords.isKeyword(word.toLowerCase())){
				builder.append(word).append(" ");
			}
		}
		return builder.toString().trim();
	}

	public static String replaceSymbolByRegex(String sourceStr, String regex){
		Pattern pattern =  Pattern.compile(regex);
		Matcher matcher = pattern.matcher(sourceStr);
		return matcher.replaceAll(" ");
	}

	/**
	 * the split rule is as follows :
	 * 
	 * P -> sT | OT
	 * s -> a+
	 * O -> Aa+ | AA+
	 * T -> OT | e
	 * 
	 * s : word start with low letter
	 * T: word start with upper letter
	 * a: low letter
	 * A: upper letter
	 * 
	 * test case: 
	 * "MFs", "CVSDecoratorPreferencesPage", "needsSaving", "IDEs", "CVSUIPlugin"
	 * 
	 * @param word
	 * @return
	 */
	public List<String> splitWordIntoWords(String word) {
		List<String> subWords = P(word);
		return subWords;
	}

	private List<String> P(String word) {
		List<String> subWords = new ArrayList<String>();
	
		try
		{
			char ch = word.charAt(0);
			if(Character.isUpperCase(ch)){
				int next = O(word, 0, subWords);
				T(word, next, subWords);
			} else if(Character.isLowerCase(ch)){
				int next = s(word, 0, subWords);
				T(word, next, subWords);
			}
		}catch(StringIndexOutOfBoundsException e){
			System.out.println("word: " + word);
		}
		return subWords;
	}

	private void T(String word, int i, List<String> subWords) {
		if(i >= word.length())
			return;
		
		if(Character.isUpperCase(word.charAt(i))){
			int next = O(word, i, subWords);
			T(word, next, subWords);
		}else{
//			System.out.println("Error! the first letter is not in upper case! ");
		}			
	}

	private int O(String word, int i, List<String> subWords) {
		int j = i + 1;
		if(j >= word.length()) 
			return j;
		
		if(Character.isLowerCase(word.charAt(j))){
			while(++j < word.length() && Character.isLowerCase(word.charAt(j))) 
				;
		} else {
			while(++j < word.length() && Character.isUpperCase(word.charAt(j))) 
				;
			
			if(j < word.length() 
					&& Character.isLowerCase(word.charAt(j)) 
					&& word.charAt(j) != 's'
					&& j != word.length() - 1)
				j --;
		}		
		
		subWords.add(StringUtils.firstUpperCase(word.substring(i, j)));
		return j;
	}

	private int s(String word, int i, List<String> subWords) {
		int j = i;
		while(++j < word.length() && Character.isLowerCase(word.charAt(j))) 
			;
		subWords.add(StringUtils.firstUpperCase(word.substring(i, j)));
		return j;
	}	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		 // "MFs", "CVSDecoratorPreferencesPage", "needsSaving", "IDEs", "CVSUIPlugin"
		StringSpliter ss = StringSpliter.getDefaultSpliter();
		String[] words={"MFs", "CVSDecoratorPreferencesPage", "needsSaving", "IDEs", "CVSUIPlugin"};
		for(String word:words){
			System.out.println(ss.splitWordIntoWords(word));
		}
	}
}
